package com.orientation.service.impl;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.orientation.commom.exception.CustomException;
import com.orientation.dto.AllocateClassParamDto;
import com.orientation.dto.StudentImportDto;
import com.orientation.dto.UserLoginParamDto;
import com.orientation.entity.*;
import com.orientation.entity.Class;
import com.orientation.enums.ExcelStudentEnum;
import com.orientation.mapper.*;
import com.orientation.service.*;
import com.orientation.utils.AesUtil;
import com.orientation.utils.BeanConvertUtils;
import com.orientation.utils.PageUtils;
import com.orientation.vo.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.orientation.utils.IDCardUtils.isIDNumber;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 学生 服务实现类
 * </p>
 *
 * @author xuandian
 * @since 2022-3-9
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
    @Value("${file.upload-path}")
    private String uploadPath;

    @Resource
    private HttpServletRequest request;

    @Resource
    private MajorService majorService;

    @Resource
    private ClassService classService;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private MajorMapper majorMapper;
    @Resource
    private ClassMapper classMapper;
    @Resource
    private CollegeMapper collegeMapper;
    @Resource
    private StudentService studentService;
    @Resource
    private BedService bedService;
    @Resource
    private BedMapper bedMapper;
    @Resource
    private FilesService filesService;
    @Resource
    private RoomMapper roomMapper;
    @Resource
    private BuildingService buildingService;
    @Resource
    private ReceiveService receiveService;
    @Resource
    private GoodsService goodsService;
    @Resource
    private ReserveService reserveService;
    @Resource
    private CollegeService collegeService;


    @Override
    public IPage<StudentPageVo> findStudentVoPage(Page<StudentPageVo> page, String collegeName, String majorName, String studentName, String grade) {
        IPage<StudentPageVo> studentVoPage = studentMapper.findStudentVoPage(page, collegeName, majorName, studentName, grade);
        //去重
        List<StudentPageVo> distinct = studentVoPage.getRecords().stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getIdCardNo))), ArrayList::new));
        for (StudentPageVo studentPageVo : distinct) {
            if (!StringUtils.hasLength(studentPageVo.getCollegeName())) {
                studentPageVo.setCollegeName("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getMajorName())) {
                studentPageVo.setMajorName("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getMobilePhone())) {
                studentPageVo.setMobilePhone("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getGender())) {
                studentPageVo.setGender("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getPolitical())) {
                studentPageVo.setPolitical("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getDomicilePlaceCity())) {
                studentPageVo.setDomicilePlaceCity("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getEmail())) {
                studentPageVo.setEmail("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getStudentId())) {
                studentPageVo.setStudentId("--");
            }
            if (!StringUtils.hasLength(studentPageVo.getPresentAddress())) {
                studentPageVo.setPresentAddress("--");

            }
            if (!StringUtils.hasLength(studentPageVo.getDomicilePlaceAddress())) {
                studentPageVo.setDomicilePlaceAddress("--");
            }
        }
        return studentVoPage;
    }

    @Override
    public Page<StudentPageVo> queryStudentPageVo(Integer pageNum, Integer pageSize, String collegeId, String majorId, String studentName, String grade, String domicilePlaceProvince) {
        List<StudentPageVo> studentPageVos = new ArrayList<>();
        LambdaQueryWrapper<Student> query = new LambdaQueryWrapper<>();
        if (StringUtils.hasLength(collegeId)) {
            query.eq(Student::getCollegeId, collegeId);
        }
        if (StringUtils.hasLength(collegeId)) {
            query.eq(Student::getCollegeId, collegeId);
        }

        if (StringUtils.hasLength(majorId)) {
            query.eq(Student::getMajorId, majorId);
        }
        if (StringUtils.hasLength(studentName)) {
            query.eq(Student::getStudentName, studentName);
        }
        if (StringUtils.hasLength(grade)) {
            query.eq(Student::getGrade, grade);
        }
        if (StringUtils.hasLength(domicilePlaceProvince)) {
            query.like(Student::getDomicilePlaceProvince, domicilePlaceProvince);
        }
        List<Student> students = studentMapper.selectList(query);
        if (!CollectionUtils.isEmpty(students)) {

            List<Student> distinct = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getIdCardNo))), ArrayList::new));
            //从List<T>取某个学生id属性值 去重
            List<String> collectMajorId = distinct.stream().map(Student::getMajorId).distinct().collect(toList());
            List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>().in(Major::getSid, collectMajorId));
            if (!CollectionUtils.isEmpty(majors)) {
                List<Major> distinctMajor = majors.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Major::getSid))), ArrayList::new));
                //从List<T>取某个学生id属性值 去重
                List<String> collectCollegeId = distinctMajor.stream().map(Major::getCollegeId).distinct().collect(toList());
                List<College> colleges = collegeMapper.selectList(new LambdaQueryWrapper<College>().in(College::getSid, collectCollegeId));
                studentPageVos = BeanConvertUtils.copyListProperties(distinct, StudentPageVo::new);
                if (!CollectionUtils.isEmpty(studentPageVos)) {
                    for (StudentPageVo studentPageVo : studentPageVos) {
                        for (Major major : majors) {
                            if (major.getSid().equals(studentPageVo.getMajorId())) {
                                studentPageVo.setMajorName(major.getMajorName());
                            }
                        }
                        for (College college : colleges) {
                            if (college.getSid().equals(studentPageVo.getCollegeId())) {
                                studentPageVo.setCollegeName(college.getCollegeName());
                            }
                        }
                        if (!StringUtils.hasLength(studentPageVo.getCollegeName())) {
                            studentPageVo.setCollegeName("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getMajorName())) {
                            studentPageVo.setMajorName("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getMobilePhone())) {
                            studentPageVo.setMobilePhone("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getGender())) {
                            studentPageVo.setGender("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getPolitical())) {
                            studentPageVo.setPolitical("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getDomicilePlaceCity())) {
                            studentPageVo.setDomicilePlaceCity("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getEmail())) {
                            studentPageVo.setEmail("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getStudentId())) {
                            studentPageVo.setStudentId("--");
                        }
                        if (!StringUtils.hasLength(studentPageVo.getPresentAddress())) {
                            studentPageVo.setPresentAddress("--");

                        }
                        if (!StringUtils.hasLength(studentPageVo.getDomicilePlaceAddress())) {
                            studentPageVo.setDomicilePlaceAddress("--");
                        }
                    }

                }
            }
        }
        studentPageVos = studentPageVos.stream().sorted(Comparator.comparing(StudentPageVo::getStudentName)).collect(Collectors.toList());
        return PageUtils.getPage(studentPageVos, pageNum, pageSize);
    }


    //  /**
//     * 导出
//     * @param collegeId
//     * @param majorId
//     * @param className
//     * @param studentName
//     * @param allocateDate
//     * @param response
//     */
//    @Override
//    public void statisticsByUnitExport(String collegeId, String majorId, String className, String studentName, String allocateDate, HttpServletResponse response) {
//
//        List<StudentClassInfoVo> studentClassInfoVos = getStudentClassInfoVos(collegeId, majorId, className, studentName, allocateDate);
//        String name=null;
//        if (CollectionUtils.isEmpty(studentClassInfoVos) ) {
//            name ="已分配班级学生";
//        }else {
//            name = studentClassInfoVos.get(0).getMajorName() + "_" + studentClassInfoVos.get(0).getClassName() + "(已分配班级学生)";
//
//        }
//        // System.out.println(studentClassInfoVos.get(0).getClassName());
//        //用于匹配数据
//        String[] key = ExportEnums.CLASS_STUDENTS_ASSIGNED_KEY.getValue();
//        //用于展示列名
//        String[] columnName = ExportEnums.CLASS_STUDENTS_ASSIGNED_NAME.getValue();
//        List<Map<String, Object>> datas = ExportXlsUtil.listToMap(studentClassInfoVos);
//        ExportXlsUtil.exportExecl(datas, name, name, key, columnName, response);
//    }

    @Override
    public IPage<StudentClassInfoVo> queryStudentClass(Integer pageNum, Integer pageSize, String collegeId, String majorId, String className, String studentName, String allocateDate, String adviserId) {


        String type = "2";
        List<StudentClassInfoVo> studentClassInfoVos = this.getStudentClassInfoVos(collegeId, majorId, className, studentName, allocateDate, "2", null);
        if (CollectionUtils.isEmpty(studentClassInfoVos)) {
            throw new CustomException("18", "暂无信息");
        }
        List<StudentClassInfoVo> studentClassInfoVoList = studentClassInfoVos.stream().filter((StudentClassInfoVo s) -> s.getAdviserId().equals(adviserId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(studentClassInfoVoList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        }
        return PageUtils.getPage(studentClassInfoVoList, pageNum, pageSize);
    }

    @Override
    public void statisticsExport(String adviserId, String majorId, String className, String studentName, String allocateDate, HttpServletResponse response) {
        List<StudentClassInfoVo> studentClassInfoVos = getStudentClassInfoVos(null, majorId, className, studentName, allocateDate, "2", null);
        List<StudentClassInfoVo> studentClassInfoVoList = studentClassInfoVos.stream().filter((StudentClassInfoVo s) -> s.getAdviserId().equals(adviserId)).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(studentClassInfoVoList)) {
            ExcelWriter writer = ExcelUtil.getWriter(true);
            writer.addHeaderAlias("studentId", "学号");
            writer.addHeaderAlias("studentName", "姓名");
            writer.addHeaderAlias("idCardNo", "身份证号");
            writer.addHeaderAlias("gender", "性别");
            writer.addHeaderAlias("nation", "民族");
            writer.addHeaderAlias("grade", "年级");
            writer.addHeaderAlias("collegeName", "学院名称");
            writer.addHeaderAlias("majorName", "专业名称");
            writer.addHeaderAlias("className", "班级名称");
            writer.addHeaderAlias("allocateDate", "加入班级时间");
            writer.addHeaderAlias("classCode", "班级序号");
            writer.setOnlyAlias(true);
            writer.write(studentClassInfoVoList, true);

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=StudentClassExport.xlsx");
            ServletOutputStream out = null;
            try {
                out = response.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        } else {
            throw new CustomException("18", "该条件下没有学生数据");
        }
    }


    @Override
    public void insertStudent(Student student) {
        if (student != null) {
            boolean idNumber = isIDNumber(student.getIdCardNo());
            if (!StringUtils.hasLength(student.getCollegeId())) {
                throw new CustomException("18", "请选择学生所在学院");
            } else if (!StringUtils.hasLength(student.getMajorId())) {
                throw new CustomException("18", "请选择学生所在学院的专业");
            }
            // else if (StringUtils.hasLength(student.getGrade()) && student.getGrade().length() != 4) {
            //     throw new CustomException("18", "年级错误");
            // }
            else if (!idNumber) {
                throw new CustomException("18", "身份证信息填写错误");
            } else if (StringUtils.hasLength(student.getMobilePhone())) {
                String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(16[5,6])|(17[0-8])|(18[0-9])|(19[1、5、8、9]))\\d{8}$";
                Pattern p = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
                Matcher m = p.matcher(student.getMobilePhone());
                if (!m.matches()) {
                    throw new CustomException("18", "手机号码填写错误");
                }
            }
            Student student1 = studentMapper.selectOne(new LambdaQueryWrapper<Student>().eq(Student::getIdCardNo, student.getIdCardNo()));
            if (student1 != null) {
                throw new CustomException("18", "此学生已经存在,请勿重复添加");
            }
            String pass = student.getIdCardNo().substring(student.getIdCardNo().length() - 6);
            // student.setPassword(AesUtil.encrypt(pass));
            // System.out.println(AesUtil.encrypt(pass));
            student.setPassword(pass);
            System.out.println(student.getPassword());
            LocalDate currentDate = LocalDate.now();
            int year = currentDate.getYear();
            student.setGrade(String.valueOf(year));
            student.setEntryDate(currentDate);
            student.setAvatar("http://localhost:9998/files/default-avatar.jpg");
            save(student);
        }
    }

    @Override
    public IPage<Student> queryNullClassId(Integer pageNum, Integer pageSize, String majorId, String studentName, String adviserId) {
        Page<Student> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Student> query = new LambdaQueryWrapper<>();
        if (!StringUtils.hasLength(adviserId)) {
            throw new CustomException("18", "重新登录");
        }
        List<Major> majorList = majorService.list(new LambdaQueryWrapper<Major>().eq(Major::getAdviserId, adviserId));
        if (CollectionUtils.isEmpty(majorList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        } else {
            List<String> majorListIds = majorList.stream().map(Major::getSid).collect(Collectors.toList());
            query.in(Student::getMajorId, majorListIds);
        }

        if (StringUtils.hasLength(studentName)) {
            query.eq(Student::getStudentName, studentName);
        }
        query.isNull(Student::getClassId);
        page = studentMapper.selectPage(page, query);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            throw new CustomException("18", "当前暂无数据");
        }
        List<Student> studentList = page.getRecords().stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getIdCardNo()))), ArrayList::new));
        List<Student> students = studentList.stream().filter((Student s) -> s.getMajorId().equals(majorId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(students)) {
            throw new CustomException("18", "当前专业没有需要处理学生信息");
        }
        //去重后的记录
        page.setRecords(students);
        //去重后的总记录数量
        page.setTotal(students.size());
        return page;
    }


    @Override
    public IPage<Student> queryNotNullClassId(Integer pageNum, Integer pageSize, String majorId, String studentName, String adviserId) {
        Page<Student> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Student> query = new LambdaQueryWrapper<>();

        List<Major> majorList = majorService.list(new LambdaQueryWrapper<Major>().eq(Major::getAdviserId, adviserId));
        if (CollectionUtils.isEmpty(majorList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        } else {
            List<String> majorListIds = majorList.stream().map(Major::getSid).collect(Collectors.toList());
            query.in(Student::getMajorId, majorListIds);
        }
        if (StringUtils.hasLength(studentName)) {
            query.eq(Student::getStudentName, studentName);
        }
        query.isNotNull(Student::getClassId);
        page = studentMapper.selectPage(page, query);
        if (CollectionUtils.isEmpty(page.getRecords())) {
            throw new CustomException("18", "当前暂无数据");
        }
        List<Student> studentList = page.getRecords().stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getIdCardNo()))), ArrayList::new));
        //查看自己所在专业学生
        List<Student> students = studentList.stream().filter((Student s) -> s.getMajorId().equals(majorId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(students)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        }
        //去重后的记录
        page.setRecords(students);
        //去重后的总记录数量
        page.setTotal(students.size());
        return page;
    }


    //  导入 （模板错误）
    @Override
    public List<Student> importStudentInfos(MultipartFile file) {
        ExcelReader reader = null;

        String fileName = file.getOriginalFilename();
        assert fileName != null;
        if (!fileName.contains(".xlsx")) {
            throw new CustomException("-17", "文件格式不正确");
        }
        try {
            reader = ExcelUtil.getReader(file.getInputStream());
        } catch (IOException e) {
            throw new CustomException("-17", "解析文件失败");
        }
        reader.addHeaderAlias("专业代码", "majorCode");
        reader.addHeaderAlias("姓名", "studentName");
        reader.addHeaderAlias("民族", "nation");
        reader.addHeaderAlias("手机号", "mobilePhone");
        reader.addHeaderAlias("身份证号", "idCardNo");
        reader.addHeaderAlias("性别", "gender");
        reader.addHeaderAlias("出生日期", "birth");
        reader.addHeaderAlias("籍贯省", "domicilePlaceProvince");
        reader.addHeaderAlias("籍贯市", "domicilePlaceCity");
        reader.addHeaderAlias("政治面貌", "political");
        reader.addHeaderAlias("婚姻状况", "marital");
        reader.addHeaderAlias("户籍地址", "domicilePlaceAddress");
        reader.addHeaderAlias("居住地址", "presentAddress");
        reader.addHeaderAlias("电子邮件", "email");
        List<StudentImportVo> studentImportVoList = reader.readAll(StudentImportVo.class);
        validateImport(studentImportVoList);
        List<Student> studentList = new ArrayList<>();
        for (StudentImportVo studentImportVo : studentImportVoList) {
            Student student = new Student();
            BeanUtils.copyProperties(studentImportVo, student);
            Major major = majorService.findByMajorCode(studentImportVo.getMajorCode());
            student.setCollegeId(major.getCollegeId());
            student.setMajorId(major.getSid());
            String pass = studentImportVo.getIdCardNo().substring(studentImportVo.getIdCardNo().length() - 6);
            student.setPassword(AesUtil.encrypt(pass));
            LocalDate currentDate = LocalDate.now();
            int year = currentDate.getYear();
            student.setGrade(String.valueOf(year));
            student.setEntryDate(currentDate);
            studentList.add(student);
        }
        saveBatch(studentList);
        return studentList;
    }

    @Override
    @Transactional
    public void importStudentPileInfo(MultipartFile file) {
        ExcelReader reader = null;

        String fileName = file.getOriginalFilename();
        assert fileName != null;
        if (ObjectUtil.isEmpty(file)) {
            throw new CustomException("18", "请选择上传的文件");
        }
        String end = Objects.requireNonNull(file.getOriginalFilename()).substring(file.getOriginalFilename().lastIndexOf(".") + 1);
        if (!"xls".equalsIgnoreCase(end) && !"xlsx".equalsIgnoreCase(end)) {
            throw new CustomException("18", "只支持excel类型");
        }
        try {
            reader = ExcelUtil.getReader(file.getInputStream());
        } catch (IOException e) {
            throw new CustomException("-17", "解析文件失败");
        }
        //检验表格人是否正确
        Workbook workbook = getWorkbook(file);
        Sheet sheet = workbook.getSheet("Sheet1");
        //校验表头信息
        Row titleRow = sheet.getRow(0);
        //表头检验错误进行提示
        if (ExcelStudentEnum.isInclude(titleRow.getCell(0).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(1).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(2).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(3).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(4).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(5).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(6).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(7).getStringCellValue())) {
            throw new CustomException("18", "请使用正确的模板");
        }

        reader.addHeaderAlias("姓名", "studentName");
        reader.addHeaderAlias("身份证号", "idCardNo");
        reader.addHeaderAlias("性别", "gender");
        reader.addHeaderAlias("学院", "collegeName");
        reader.addHeaderAlias("专业", "majorName");
        reader.addHeaderAlias("民族", "nation");
        // reader.addHeaderAlias("年级", "grade");
        reader.addHeaderAlias("籍贯省", "domicilePlaceProvince");
        List<StudentImportDto> studentImportDtos = reader.readAll(StudentImportDto.class);
        //数据解析判断
        this.validateImports(studentImportDtos);
        //List<Student> studentList = new ArrayList<>();
        List<Student> updateStudent = new ArrayList<>();

        List<Major> majorList = majorMapper.selectList(new LambdaQueryWrapper<Major>().eq(Major::getState, 1));
        if (!CollectionUtils.isEmpty(studentImportDtos) && !CollectionUtils.isEmpty(majorList)) {
            for (StudentImportDto student : studentImportDtos) {
                for (Major major : majorList) {
                    if (major.getMajorName().equals(student.getMajorName())) {
                        student.setMajorId(major.getSid());
                        student.setCollegeId(major.getCollegeId());
                    }
                }
            }
        }
        List<Student> studentList = BeanConvertUtils.copyListProperties(studentImportDtos, Student::new);
        //已经存在的 学生
        List<Student> students = studentService.list();
        if (!CollectionUtils.isEmpty(students)) {
            //取交集 更新
            for (Student student : studentList) {
                for (Student student1 : students) {
                    if (student1.getIdCardNo().equals(student.getIdCardNo())) {
                        student.setSid(student1.getSid());
                        student.setDeleted(0);
                        student.setClassId(student1.getClassId());
                        student.setEntryDate(student1.getEntryDate());
                        student.setStudentId(student1.getStudentId());
                        student.setMobilePhone(student1.getMobilePhone());
                        student.setBirth(student1.getBirth());
                        student.setPolitical(student1.getPolitical());
                        student.setMarital(student1.getMarital());
                        student.setDomicilePlaceCity(student1.getDomicilePlaceCity());
                        student.setDomicilePlaceAddress(student1.getDomicilePlaceAddress());
                        student.setPresentAddress(student1.getPresentAddress());
                        student.setEmail(student1.getEmail());
                        student.setStatus(student1.getStatus());
                        student.setHasClothing(student1.getHasClothing());
                        student.setHeight(student1.getHeight());
                        student.setShoeSize(student1.getShoeSize());
                        student.setWeight(student1.getWeight());
                        String pass = student.getIdCardNo().substring(student.getIdCardNo().length() - 6);
                        student.setPassword(pass);
                        updateStudent.add(student);
                    }
                }
            }
            if (!CollectionUtils.isEmpty(updateStudent)) {
                updateBatchById(updateStudent);
            }
        }
        //得到数据库不存在的数据进行入库    //取差集
        List<Student> insertPile = studentList.stream().filter(m -> !students.stream().map(Student::getIdCardNo).collect(toList()).contains(m.getIdCardNo())).collect(toList());
        //给对象属性赋值
        if (!CollectionUtils.isEmpty(insertPile)) {
            for (Student student : insertPile) {
                student.setAvatar("http://localhost:9998/files/default-avatar.jpg");
                String pass = student.getIdCardNo().substring(student.getIdCardNo().length() - 6);
                student.setPassword(pass);
                LocalDate currentDate = LocalDate.now();
                int year = currentDate.getYear();
                 student.setGrade(String.valueOf(year));
                student.setEntryDate(currentDate);
            }
            saveBatch(insertPile);
        }

    }


    private void validateImports(List<StudentImportDto> studentImportDtos) {
        StringBuilder sb = new StringBuilder();
        sb.append("错误信息：\n");
        boolean flag = false;
        //校验是否有重复的学生信息  过滤为空的id在比较检验
        Map<String, Long> collect = studentImportDtos.stream().filter(t -> StringUtils.hasLength(t.getIdCardNo())).collect(groupingBy(StudentImportDto::getIdCardNo, Collectors.counting()));
        List<String> IDCards = collect.entrySet().stream().filter(entry -> entry.getValue() > 1).map(Map.Entry::getKey).collect(toList());
        if (IDCards.size() > 0) {
            throw new CustomException("-18", "学生身份证（" + IDCards + "）数据重复，请确认后重新上传");
        }

        List<Major> majorList = majorService.queryMaj(null, 1);

        //按照专业名名分组   进行判匹配//
        if (!CollectionUtils.isEmpty(majorList)) {
            Map<String, List<Major>> pileMap = majorList.stream().collect(groupingBy(Major::getMajorName));
            List<String> collectCollegeId = majorList.stream().map(Major::getCollegeId).distinct().collect(toList());
            List<College> colleges = collegeMapper.selectList(new LambdaQueryWrapper<College>().in(College::getSid, collectCollegeId));
            if (!CollectionUtils.isEmpty(colleges)) {
                Map<String, List<College>> listMap = colleges.stream().collect(groupingBy(College::getCollegeName));
                if (!CollectionUtils.isEmpty(studentImportDtos)) {
                    for (int i = 0; i < studentImportDtos.size(); i++) {
                        StudentImportDto studentImportDto = studentImportDtos.get(i);
                        //姓名
                        if (!StringUtils.hasLength(studentImportDto.getStudentName())) {
                            sb.append("第").append(i + 1).append("行，").append("学生姓名不能为空").append("\n");
                            flag = true;
                        }
                        //身份证号
                        if (!StringUtils.hasLength(studentImportDto.getIdCardNo())) {
                            sb.append("第").append(i + 1).append("行，").append("身份证不能为空").append("\n");
                            flag = true;
                        }

                        if (StringUtils.hasLength(studentImportDto.getIdCardNo()) && !IdcardUtil.isValidCard18(studentImportDto.getIdCardNo())) {
                            sb.append("第").append(i + 1).append("行，").append("身份证格式非法").append("\n");
                            flag = true;
                        }//性别
                        if (!StringUtils.hasLength(studentImportDto.getGender())) {
                            sb.append("第").append(i + 1).append("行，").append("学生性别不能为空").append("\n");
                            flag = true;
                        }
                        if (StringUtils.hasLength(studentImportDto.getGender()) && !"男".equals(studentImportDto.getGender()) && !"女".equals(studentImportDto.getGender())) {
                            sb.append("第").append(i + 1).append("行，").append("性别只能是男/女").append("\n");
                            flag = true;
                        }
                        //学院
                        if (!StringUtils.hasLength(studentImportDto.getCollegeName())) {
                            sb.append("第").append(i + 1).append("行，").append("学院不能为空").append("\n");
                            flag = true;
                        }
                        if (StringUtils.hasLength(studentImportDto.getCollegeName()) && CollectionUtils.isEmpty(listMap.get(studentImportDto.getCollegeName()))) {
                            sb.append("第").append(i + 1).append("行，").append("专业没有先维护，请先添加学院信息").append("\n");
                            flag = true;
                        }
                        //
                        //专业
                        if (!StringUtils.hasLength(studentImportDto.getMajorName())) {
                            sb.append("第").append(i + 1).append("行，").append("专业不能为空").append("\n");
                            flag = true;
                        }
                        if (StringUtils.hasLength(studentImportDto.getMajorName()) && CollectionUtils.isEmpty(pileMap.get(studentImportDto.getMajorName()))) {
                            sb.append("第").append(i + 1).append("行，").append("专业没有先维护，请先添加专业信息").append("\n");
                            flag = true;
                        }

                        //民族
                        if (!StringUtils.hasLength(studentImportDto.getNation())) {
                            sb.append("第").append(i + 1).append("行，").append("民族不能为空").append("\n");
                            flag = true;
                        }
                        //年级
                        // if (!StringUtils.hasLength(studentImportDto.getGrade())) {
                        //     sb.append("第").append(i + 1).append("行，").append("年级不能为空").append("\n");
                        //     flag = true;
                        // }
                        //年级
                        if (!StringUtils.hasLength(studentImportDto.getDomicilePlaceProvince())) {
                            sb.append("第").append(i + 1).append("行，").append("籍贯省不能为空").append("\n");
                            flag = true;
                        }

                    }
                }
            } else {
                throw new CustomException("-17", "请先维护学院信息");
            }
        } else {
            throw new CustomException("-17", "请先维护专业信息");
        }
        if (flag) {
            throw new CustomException("-17", sb.toString());
        }

    }

    @Override
    public void export(HttpServletResponse response) {
        List<StudentVo> studentVoList = studentMapper.findAllStudentVoAllocated();
        if (CollectionUtils.isEmpty(studentVoList)) {
            throw new CustomException("18","暂无数据");

        }
        List<StudentExportVo> exportVoList = new ArrayList<>();
        for (StudentVo studentVo : studentVoList) {
            StudentExportVo exportVo = new StudentExportVo();
            BeanUtils.copyProperties(studentVo, exportVo);
            exportVo.setCollegeName(studentVo.getMyCollege().getCollegeName());
            exportVo.setMajorName(studentVo.getMyMajor().getMajorName());
            exportVo.setMajorCode(studentVo.getMyMajor().getMajorCode());
            exportVo.setClassName(studentVo.getMyClass().getClassName());
            // exportVo.setClassCode(studentVo.getMyClass().getClassCode());
            exportVo.setAdviser(studentVo.getMyClass().getAdviser());
            exportVoList.add(exportVo);
        }

        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.addHeaderAlias("majorCode", "专业代码");
        writer.addHeaderAlias("studentName", "姓名");
        writer.addHeaderAlias("nation", "民族");
        writer.addHeaderAlias("mobilePhone", "手机号");
        writer.addHeaderAlias("idCardNo", "身份证号");
        writer.addHeaderAlias("gender", "性别");
        writer.addHeaderAlias("birth", "出生日期");
        writer.addHeaderAlias("domicilePlaceProvince", "籍贯省");
        writer.addHeaderAlias("domicilePlaceCity", "籍贯市");
        writer.addHeaderAlias("political", "政治面貌");
        writer.addHeaderAlias("marital", "婚姻状况");
        writer.addHeaderAlias("domicilePlaceAddress", "户籍地址");
        writer.addHeaderAlias("presentAddress", "居住地址");
        writer.addHeaderAlias("email", "电子邮件");
        writer.addHeaderAlias("collegeName", "学院名称");
        writer.addHeaderAlias("majorName", "专业名称");
        writer.addHeaderAlias("className", "班级名称");
        writer.addHeaderAlias("classCode", "班级序号");
        writer.addHeaderAlias("adviser", "辅导员");
        writer.setOnlyAlias(true);
        writer.write(exportVoList, true);

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=StudentExport.xlsx");
        ServletOutputStream out = null;
        try {
            out = response.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
        writer.flush(out, true);
        writer.close();
        IoUtil.close(out);
    }

    @Override
    public void updateStudentClass(AllocateClassParamDto allocateClassParamDto) {

        if (allocateClassParamDto == null) {
            throw new CustomException("18", "请填写必要的参数");
        }
        List<Student> studentList = studentMapper.selectList(new LambdaQueryWrapper<Student>().in(Student::getSid, allocateClassParamDto.getIdList()));
        if (StringUtils.hasLength(allocateClassParamDto.getClassId())) {
            if (allocateClassParamDto.getClassId().equals(studentList.get(0).getClassId())) {
                throw new CustomException("18", "当前班级没变，请选择去其他班级");
            }
            for (Student student : studentList) {
                student.setClassId(allocateClassParamDto.getClassId());
                student.setAllocateDate(LocalDate.now());
            }
            updateBatchById(studentList);

        } else {
            throw new CustomException("18", "请填写所需要微调得班级");
        }

    }

    @Override
    public IPage<StudentClassInfoVo> queryStudentIdBed(Integer pageNum, Integer pageSize, String collegeId, String majorId, String className, String studentName, String sexType, String adviserId) {
        List<StudentClassInfoVo> studentClassInfoVos = getStudentClassInfoVos(collegeId, majorId, className, studentName, null, "1", null);
        if (CollectionUtils.isEmpty(studentClassInfoVos)) {
            throw new CustomException("18", "暂无信息");
        }
        if (!StringUtils.hasLength(adviserId)) {
            throw new CustomException("18", "adviserId必须填写");
        }
        List<StudentClassInfoVo> studentClassVoList = studentClassInfoVos.stream().filter((StudentClassInfoVo s) -> s.getAdviserId().equals(adviserId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(studentClassVoList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        }
        List<String> studentIds = studentClassInfoVos.stream().map(StudentClassInfoVo::getStudentId).distinct().collect(toList());
        //获取已经分床位学生学号
        List<Bed> bedList = bedService.list(Wrappers.<Bed>lambdaQuery().in(!CollectionUtils.isEmpty(studentIds), Bed::getStudentId, studentIds));

        //两个对象根据学生id 取差集
        List<StudentClassInfoVo> studentInfoVoList = studentClassInfoVos.stream().filter(
                m -> !bedList.stream().map(Bed::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());
        if (!StringUtils.hasLength(sexType)) {
            throw new CustomException("18", "男女类类型必须选择");
        }
        List<StudentClassInfoVo> studentClassInfoVoList = new ArrayList<>();

        //1 男生2 女生
        if ("1".equals(sexType)) {
            studentClassInfoVoList = studentInfoVoList.stream().filter((StudentClassInfoVo vo) -> StringUtils.hasLength(vo.getGender()) && "男".equals(vo.getGender())).collect(toList());
        } else {
            studentClassInfoVoList = studentInfoVoList.stream().filter((StudentClassInfoVo vo) -> StringUtils.hasLength(vo.getGender()) && "女".equals(vo.getGender())).collect(toList());
        }
        return PageUtils.getPage(studentClassInfoVoList, pageNum, pageSize);
    }

    @Override
    public IPage<StudentClassInfoVo> queryStudentIdGoods(Integer pageNum, Integer pageSize, String collegeId, String majorId, String className, String studentName) {
        List<StudentClassInfoVo> studentClassInfoVos = getStudentClassInfoVos(collegeId, majorId, className, studentName, null, "1", null);
        return PageUtils.getPage(studentClassInfoVos, pageNum, pageSize);
    }

    @Override
    public StudentPageVo studentClassInfoVo(String id) {
        Student student = studentMapper.selectById(id);
        Major major = majorMapper.selectById(student.getMajorId());
        College college = collegeMapper.selectById(major.getCollegeId());
        StudentPageVo classInfoVo = new StudentPageVo();
        BeanUtils.copyProperties(student, classInfoVo);
        classInfoVo.setCollegeName(college.getCollegeName());
        classInfoVo.setMajorName(major.getMajorName());
        return classInfoVo;
    }

    private void validateImport(List<StudentImportVo> studentImportVoList) {
        StringBuilder sb = new StringBuilder();
        sb.append("错误信息：\n");
        boolean flag = false;


        for (int i = 0; i < studentImportVoList.size(); i++) {
            StudentImportVo studentImportVo = studentImportVoList.get(i);
            if (!StringUtils.hasLength(studentImportVo.getStudentName())) {
                sb.append("第").append(i + 1).append("行，").append("学生姓名不能为空").append("\n");
                flag = true;
            }
            //身份证号
            if (!IdcardUtil.isValidCard18(studentImportVo.getIdCardNo())) {
                sb.append("第").append(i + 1).append("行，").append("身份证格式非法").append("\n");
                flag = true;
            }
            //性别
            if (!"男".equals(studentImportVo.getGender()) && !"女".equals(studentImportVo.getGender())) {
                sb.append("第").append(i + 1).append("行，").append("性别只能是男/女").append("\n");
                flag = true;
            }
            if (!StringUtils.hasLength(studentImportVo.getMajorCode())) {
                sb.append("第").append(i + 1).append("行，").append("专业代码不能为空").append("\n");
                flag = true;
            }
            //民族
            if (!StringUtils.hasLength(studentImportVo.getNation())) {
                sb.append("第").append(i + 1).append("行，").append("民族不能为空").append("\n");
                flag = true;
            }
        }

        if (flag) {
            throw new CustomException("-17", sb.toString());
        }
    }

    /**
     * 按照专业   班级 两个维度统计已经分配班级学生
     *
     * @param collegeId
     * @param majorId
     * @param className
     * @param studentName
     * @param allocateDate
     * @return StudentClassInfoVo
     */
    @Override
    public List<StudentClassInfoVo> getStudentClassInfoVos(String collegeId, String majorId, String className, String studentName, String allocateDate, String type, String studentId) {
        List<StudentClassInfoVo> studentClassInfoVos = new ArrayList<>();
        LambdaQueryWrapper<Student> queryStudent = new LambdaQueryWrapper<Student>();
        if ("1".equals(type)) { //分配床位  学生id 不为空
            queryStudent.isNotNull(true, Student::getStudentId);
        } else if ("2".equals(type)) {  //已经班级分配
            queryStudent.isNotNull(true, Student::getClassId);
        } else if ("3".equals(type)) {
            queryStudent.isNotNull(true, Student::getClassId).isNotNull(true, Student::getStudentId);
        }
        if (StringUtils.hasLength(collegeId)) {
            queryStudent.eq(Student::getCollegeId, collegeId);
        }
        if (StringUtils.hasLength(majorId)) {
            queryStudent.eq(Student::getMajorId, majorId);
        }
        if (StringUtils.hasLength(type) && StringUtils.hasLength(studentId)) {
            queryStudent.eq(Student::getStudentId, studentId);
        }
        // if (!StringUtils.hasLength(className)) {
        //     throw new CustomException("18", "班级为必填项");
        // }
        Class aClass = new Class();
        if (StringUtils.hasLength(className)) {
            aClass = classMapper.selectOne(new LambdaQueryWrapper<Class>().eq(Class::getClassName, className));
        }
        if (StringUtils.hasLength(className) && aClass == null) {
            return new ArrayList<>();
        }
        if (aClass != null && StringUtils.hasLength(aClass.getSid())) {
            queryStudent.eq(Student::getClassId, aClass.getSid());
        }
        if (StringUtils.hasLength(studentName)) {
            queryStudent.like(Student::getStudentName, studentName);
        }
        if (StringUtils.hasLength(studentId)) {
            queryStudent.eq(Student::getStudentId, studentId);
        }

        if (StringUtils.hasLength(allocateDate)) {
            queryStudent.like(Student::getAllocateDate, allocateDate);
        }
        List<Student> students = studentMapper.selectList(queryStudent);
        studentClassInfoVos = getStudentClassInfoAnalysis(studentClassInfoVos, students);
        return studentClassInfoVos;
    }

    private List<StudentClassInfoVo> getStudentClassInfoAnalysis(List<StudentClassInfoVo> studentClassInfoVos, List<Student> students) {
        if (!CollectionUtils.isEmpty(students)) {
            //单个个LIst对象根据阶段名字段去重
            List<Student> distinct = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Student::getIdCardNo))), ArrayList::new));
            //从List<T>取某个学生id属性值
            List<String> collectMajorId = distinct.stream().map(Student::getMajorId).collect(toList());
            List<String> collectClassId = distinct.stream().map(Student::getClassId).collect(toList());
            List<Class> classes = classMapper.selectList(new LambdaQueryWrapper<Class>().in(Class::getSid, collectClassId));
            //查询处理匹配  减少哦数据库压力
            List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>().in(Major::getSid, collectMajorId));
            if (!CollectionUtils.isEmpty(majors)) {
                List<Major> distinctMajor = majors.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getSid()))), ArrayList::new));
                //从List<T>取某个学生id属性值 去重
                List<String> collectCollegeId = distinctMajor.stream().map(Major::getCollegeId).distinct().collect(toList());
                List<College> colleges = collegeMapper.selectList(new LambdaQueryWrapper<College>().in(College::getSid, collectCollegeId));
                studentClassInfoVos = BeanConvertUtils.copyListProperties(students, StudentClassInfoVo::new);
                for (StudentClassInfoVo classInfoVo : studentClassInfoVos) {
                    for (Class ignored : classes) {
                        if (ignored.getSid().equals(classInfoVo.getClassId())) {
                            classInfoVo.setClassName(ignored.getClassName());
                            // classInfoVo.setClassCode(ignored.getClassCode());
                            classInfoVo.setAdviserId(ignored.getAdviserId());
                        }
                    }
                    for (Major major : majors) {
                        if (major.getSid().equals(classInfoVo.getMajorId())) {
                            classInfoVo.setMajorName(major.getMajorName());
                            classInfoVo.setAdviserId(major.getAdviserId());
                        }
                    }
                    for (College college : colleges) {
                        if (college.getSid().equals(classInfoVo.getCollegeId())) {
                            classInfoVo.setCollegeName(college.getCollegeName());
                        }
                    }
                }
            }
        }
        return studentClassInfoVos;
    }

    @Override
    public void updateStudent(Student student) {
        if (student != null && StringUtils.hasLength(student.getStudentId()) && StringUtils.hasLength(student.getIdCardNo())) {
            Student one = studentService.getOne(Wrappers.<Student>lambdaQuery().eq(Student::getStudentId, student.getStudentId()).eq(Student::getIdCardNo, student.getIdCardNo()).eq(StringUtils.hasLength(student.getSid()), Student::getSid, student.getSid()));
            if (one == null) {
                throw new CustomException("18", "输入信息错误");
            }
            student.setSid(one.getSid());
            studentService.updateById(student);
        }
    }

    @Override
    public Student updateStudentAvatar(MultipartFile[] files, String sid) {
        if (!StringUtils.hasLength(sid)) {
            throw new CustomException("18", "必填参数为空");
        }
        Student student = this.getById(sid);
        if (files != null && files.length > 0) {
            List<String> stringUrls = filesService.getStringUrls(files);
            if (!CollectionUtils.isEmpty(stringUrls)) {
                student.setAvatar(stringUrls == null ? null : org.apache.commons.lang3.StringUtils.join(stringUrls, ","));
            }

        } else {
            throw new CustomException("18", "请选择头像文件");
        }
        this.updateById(student);
        return student;
    }

    @Override
    public ReportSheetVo studentReport(String studentId, String idCardNo) {
        ReportSheetVo reportSheetVo = new ReportSheetVo();

        Student student = studentService.getOne(new LambdaQueryWrapper<Student>()
                .eq(StringUtils.hasLength(studentId), Student::getStudentId, studentId)
                .eq(StringUtils.hasLength(idCardNo), Student::getIdCardNo, idCardNo));
        if (!ObjectUtils.isEmpty(student)) {
            College college = collegeMapper.selectById(student.getCollegeId());
            Major major = majorService.getById(student.getMajorId());
            Bed bed = bedMapper.selectOne(new LambdaQueryWrapper<Bed>().eq(StringUtils.hasLength(studentId), Bed::getStudentId, studentId));
            Room room = new Room();
            BeanUtils.copyProperties(student, reportSheetVo);
            Class classClass = classService.getById(student.getClassId());
            if (ObjectUtils.isNotEmpty(classClass) ) {
                reportSheetVo.setClassName(classClass.getClassName());
            }
            reportSheetVo.setCollegeName(college.getCollegeName());
            reportSheetVo.setMajorName(major.getMajorName());

            List<Receive> receives = receiveService.list(new LambdaQueryWrapper<Receive>().eq(Receive::getStudentId, student.getStudentId()));
            List<Goods> goods = goodsService.list();
            if (!CollectionUtils.isEmpty(goods)) {
                if (CollectionUtils.isEmpty(receives)) {
                    reportSheetVo.setReceiveType("待领取");
                }
                {
                    long count = receives.stream().filter(s -> s.getReceiveStatus().equals(1)).count();
                    if (count != goods.size()) {
                        reportSheetVo.setReceiveType("待领取");
                    } else if (goods.size() == receives.size()) {
                        reportSheetVo.setReceiveType("已领取");
                    }
                }
            }
            if (!ObjectUtils.isEmpty(bed)) {
                room = roomMapper.selectOne(new LambdaQueryWrapper<Room>().eq(!ObjectUtils.isEmpty(bed) && StringUtils.hasLength(bed.getRoomId()), Room::getSid, bed.getRoomId()));
                Building building = buildingService.getById(room.getBuildingId());
                reportSheetVo.setBuildingName(building.getName());
                reportSheetVo.setRoomName(room.getName());
                reportSheetVo.setFloor(building.getFloor() + "楼");
                reportSheetVo.setRegion(building.getRegion());
                reportSheetVo.setType(building.getType());
                reportSheetVo.setBedName(bed.getName() + "号床");
            }
        }

        return reportSheetVo;
    }

    @Override
    public IPage<StudentClassInfoVo> fileCheckIn(Integer pageNum, Integer pageSize, String majorId, String className, String studentName, String adviserId) {
        List<StudentClassInfoVo> studentClassInfoVos = getStudentClassInfoVos(null, majorId, className, studentName, null, "1", null);
        List<Reserve> reserves = reserveService.list(Wrappers.<Reserve>lambdaQuery().eq(Reserve::getStatus, 3));
        if (CollectionUtils.isEmpty(studentClassInfoVos)) {
            throw new CustomException("18", "暂无信息");
        }
        List<StudentClassInfoVo> insertPile = studentClassInfoVos.stream().filter(m -> !reserves.stream().map(Reserve::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());

        List<StudentClassInfoVo> studentClassInfoVoList = insertPile.stream().filter((StudentClassInfoVo s) -> s.getAdviserId().equals(adviserId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(studentClassInfoVoList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        }
        return PageUtils.getPage(studentClassInfoVoList, pageNum, pageSize);
    }

    @Override
    public void fileCheckInExport(String majorId, String className, String studentName, String adviserId, HttpServletResponse response) {
        List<StudentClassInfoVo> studentClassInfoVos = getStudentClassInfoVos(null, majorId, className, studentName, null, "1", null);
        List<Reserve> reserves = reserveService.list(Wrappers.<Reserve>lambdaQuery().eq(Reserve::getStatus, 3));
        if (CollectionUtils.isEmpty(studentClassInfoVos)) {
            throw new CustomException("18", "暂无信息");
        }
        List<StudentClassInfoVo> insertPile = studentClassInfoVos.stream().filter(m -> !reserves.stream().map(Reserve::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());

        List<StudentClassInfoVo> studentClassInfoVoList = insertPile.stream().filter((StudentClassInfoVo s) -> s.getAdviserId().equals(adviserId)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(studentClassInfoVoList)) {
            throw new CustomException("18", "只能查看自己所在专业学生信息");
        } else {
            ExcelWriter writer = ExcelUtil.getWriter(true);
            writer.addHeaderAlias("studentId", "学号");
            writer.addHeaderAlias("studentName", "姓名");
            writer.addHeaderAlias("idCardNo", "身份证号");
            writer.addHeaderAlias("gender", "性别");
            writer.addHeaderAlias("nation", "民族");
            writer.addHeaderAlias("domicilePlaceProvince", "籍贯（省）");
            writer.addHeaderAlias("grade", "年级");
            writer.addHeaderAlias("collegeName", "学院名称");
            writer.addHeaderAlias("majorName", "专业名称");
            writer.addHeaderAlias("className", "班级名称");
            // writer.addHeaderAlias("allocateDate", "加入班级时间");
            writer.addHeaderAlias("classCode", "班级序号");
            writer.setOnlyAlias(true);
            writer.write(studentClassInfoVoList, true);

            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=fileCheckInExport.xlsx");
            ServletOutputStream out = null;
            try {
                out = response.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            writer.flush(out, true);
            writer.close();
            IoUtil.close(out);
        }

    }

    @Override
    public List<StudentClassInfoVo> fileCheckInAll(String id, String studentId, String studentName) {
        List<StudentClassInfoVo> studentClassInfoVos = new ArrayList<>();
        List<Student> students = studentService.list(Wrappers.<Student>lambdaQuery().eq(StringUtils.hasLength(id), Student::getCollegeId, id)
                .or().eq(StringUtils.hasLength(id), Student::getMajorId, id).or().eq(StringUtils.hasLength(id), Student::getClassId, id)
                .eq(StringUtils.hasLength(studentId), Student::getStudentId, studentId).like(StringUtils.hasLength(studentName), Student::getStudentName, studentName));
        return getStudentClassInfoAnalysis(studentClassInfoVos, students);
    }

    @Override
    public IPage<StudentClassInfoVo> queryfileCheckInAll(Integer pageNum, Integer pageSize, String id, String studentId, String studentName) {
        List<StudentClassInfoVo> studentClassInfoVos = fileCheckInAll(id, studentId, studentName);
        List<Reserve> reserves = reserveService.list(Wrappers.<Reserve>lambdaQuery().eq(Reserve::getStatus, 3));
        if (CollectionUtils.isEmpty(studentClassInfoVos)) {
            throw new CustomException("18", "暂无信息");
        }
        List<StudentClassInfoVo> studentClassInfoVoList = studentClassInfoVos.stream().filter(m -> !reserves.stream().map(Reserve::getStudentId).collect(toList()).contains(m.getStudentId())).collect(toList());

        return PageUtils.getPage(studentClassInfoVoList, pageNum, pageSize);
    }


    @Override
    public Student login(UserLoginParamDto loginParamDto) {
        LoginVo loginVo = new LoginVo();
        Student one = getOne(Wrappers.<Student>lambdaQuery().eq(Student::getStudentId, loginParamDto.getUsername()).eq(Student::getPassword, AesUtil.encrypt(loginParamDto.getPassword())));
        if (one != null) {
            request.getSession().setAttribute("student", one);
            //讲登录信息放入缓存
            // loginVo = new LoginVo();
            // loginVo.setUserName(one.getStudentId());
            // loginVo.setLoginName(one.getPassword());
            // // loginVo.setAvatar(one.getAvatar());
            // // loginVo.setRole(one.getRoleId());
            // loginVo.setToken(one.getStudentId() + one.getPassword());
        } else {
            throw new CustomException("18", "密码用户密码错误");
        }
        return one;
    }

    @Override
    public List<Student> findByCollegeId(String id) {
        return this.list(Wrappers.<Student>lambdaQuery().eq(Student::getCollegeId, id));
    }

    @Override
    public long countByCollegeIdAndGender(String id, String gender) {
        return this.count(Wrappers.<Student>lambdaQuery().eq(Student::getCollegeId, id).eq(Student::getGender, gender).eq(Student::getDeleted, 0));
    }

    @Override
    public void allocateClass(AllocateClassParamDto classParamDto) {
        List<Student> studentList = this.list(Wrappers.<Student>lambdaQuery().in(Student::getSid, classParamDto.getIdList())).stream().sorted(Comparator.comparing(Student::getStudentName)).collect(toList());

        // String studentId = this.getOne(Wrappers.<Student>lambdaQuery().eq(Student::getClassId, classParamDto.getClassId()).orderByDesc(Student::getStudentId).last("limit 1"));
        Student one = this.getOne(Wrappers.<Student>lambdaQuery().eq(Student::getClassId, classParamDto.getClassId()).orderByDesc(Student::getStudentId).last("limit 1"));
        String studentId = "";
        if (!ObjectUtils.isEmpty(one)) {
            studentId = one.getStudentId();
        }
        int maxId = 0;
        if (StringUtils.hasLength(studentId)) {
            maxId = Integer.parseInt(studentId.substring(studentId.length() - 2));
        }
        LocalDateTime currentDate = LocalDateTime.now();
        int year = currentDate.getYear();
        String newyer = String.valueOf(year);
        Class classPo = classService.getById(classParamDto.getClassId());
        Major major = majorService.getById(classPo.getMajorId());
        College college=collegeService.getById(classPo.getCollegeId());
            String studentIdPrefix = String.format("%s%s%s%s", newyer.substring(newyer.length() - 2),college.getCollegeCode(), major.getMajorCode(), classPo.getClassCode());
        for (Student student : studentList) {

            // student.setPassword(AesUtil.encrypt(AesUtil.encrypt(student.getPassword())));
            student.setClassId(classParamDto.getClassId());
            //todo  目前实现逻辑 =》原来的学生已经产生过学号  学号不做处理 不重新产生学号，
            if (!StringUtils.hasLength(student.getStudentId())) {
                maxId++;
                String newStudentId = String.format("%s%02d", studentIdPrefix, maxId);
                student.setStudentId(newStudentId);
            }
            student.setAllocateDate(LocalDate.now());
        }
        this.saveOrUpdateBatch(studentList);
    }

    @Override
    public void updateClassId(AllocateClassParamDto allocateClassParamDto) {
        if (!ObjectUtils.isEmpty(allocateClassParamDto) && !CollectionUtils.isEmpty(allocateClassParamDto.getIdList())) {
            List<Student> studentList = this.listByIds(allocateClassParamDto.getIdList()).stream().sorted(Comparator.comparing(Student::getStudentName)).collect(toList());
            if (!CollectionUtils.isEmpty(studentList)) {
                for (Student student : studentList) {
                    student.setClassId(null);
                    student.setAllocateDate(null);
                }
                updateBatchById(studentList);
            } else {
                throw new CustomException("18", "请选择学生信息");
            }
        } else {
            throw new CustomException("18", "请选择学生信息");
        }
    }

    @Override
    public List<MajorSizeVo> studentMajor() {
        LambdaQueryWrapper<Student> queryStudent = new LambdaQueryWrapper<>();
        queryStudent.isNull(true, Student::getClassId);
        //  queryStudent.eq(Student::getDeleted, 0).eq(Student::getClassId, null);
        List<Student> students = studentMapper.selectList(queryStudent);
        List<MajorSizeVo> majorSizeVos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(students)) {
            //根据学生去重
            List<Student> students1 = students.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(c -> c.getIdCardNo()))), ArrayList::new));
            //根据专业id分组
            Map<String, List<Student>> integerListMap = students1.stream().collect(Collectors.groupingBy(Student::getMajorId));

            List<String> listMajorId = new ArrayList<>();
            //取到major id
            integerListMap.forEach((majorId, value) -> {
                listMajorId.add(majorId);
            });
            List<Major> majors = majorMapper.selectList(new LambdaQueryWrapper<Major>()
                    //   .eq(Major::getDeleted, 0)
                    .in(Major::getSid, listMajorId)
            );
            if (!CollectionUtils.isEmpty(majors)) {
                List<Major> majors1 = majors.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Major::getMajorName))), ArrayList::new));
                //根据专业id分组
                if (!CollectionUtils.isEmpty(majors1)) {
                    for (Major major : majors1) {
                        MajorSizeVo majorSizeVo = new MajorSizeVo();
                        if (StringUtils.hasLength(major.getSid()) && !CollectionUtils.isEmpty(integerListMap.get(major.getSid()))) {
                            majorSizeVo.setMajorName(major.getMajorName());
                            majorSizeVo.setNotClassIDNum(integerListMap.get(major.getSid()).size());
                            majorSizeVo.setSid(major.getSid());
                            majorSizeVos.add(majorSizeVo);
                        }

                    }

                }
            }
        }
        return majorSizeVos;
    }

    @Override
    public List<PieDataVo> getStudentProvinceGroup(String collegeId, String majorId) {
        List<PieDataVo> pieDataVoList = new ArrayList<>();
        LambdaQueryWrapper<Student> queryStudent = new LambdaQueryWrapper<>();

        if (StringUtils.hasLength(collegeId)) {
            queryStudent.eq(Student::getCollegeId, collegeId);
        }
        if (StringUtils.hasLength(majorId)) {
            queryStudent.eq(Student::getMajorId, majorId);
        }
        List<Student> list = studentMapper.selectList(queryStudent);
        Map<String, List<Student>> studentGroup = list.stream().filter(s -> StringUtils.hasText(s.getDomicilePlaceProvince())).collect(Collectors.groupingBy(Student::getDomicilePlaceProvince));
        for (Map.Entry<String, List<Student>> entry : studentGroup.entrySet()) {
            PieDataVo pieDataVo = new PieDataVo();
            pieDataVo.setName(entry.getKey());
            pieDataVo.setValue((long) entry.getValue().size());
            pieDataVoList.add(pieDataVo);
        }
        return pieDataVoList;
    }

    /**
     * 批量导入
     *
     * @param multipartFile
     */
    @Override
    @Transactional
    public void importPileInfo(MultipartFile multipartFile) {
        //获取excel表中数量列表
        List<Student> studentList = getExcelInfos(multipartFile);
        List<Student> updateStudent = new ArrayList<>();
        if (!CollectionUtils.isEmpty(studentList)) {
            //已经存在的 学生
            List<Student> students = studentMapper.selectList(new LambdaQueryWrapper<Student>()
                    //  .eq(Student::getDeleted, 0)
                    .groupBy(Student::getCollegeId)
            );
            if (!CollectionUtils.isEmpty(students)) {
                //取交集 更新
                for (Student student : studentList) {
                    for (Student student1 : students) {
                        if (student1.getIdCardNo().equals(student.getIdCardNo())) {
                            student.setSid(student1.getSid());
                            student.setDeleted(0);
                            updateStudent.add(student);
                        }
                    }
                }
                if (!CollectionUtils.isEmpty(updateStudent)) {
                    updateBatchById(updateStudent);
                }
            }
            //得到数据库不存在的数据进行入库    //取差集
            List<Student> insertPile = studentList.stream().filter(m -> !students.stream().map(Student::getIdCardNo).collect(toList()).contains(m.getIdCardNo())).collect(toList());
            //给对象属性赋值
            if (!CollectionUtils.isEmpty(insertPile)) {
                for (Student student : insertPile) {
                    String pass = student.getIdCardNo().substring(student.getIdCardNo().length() - 6);
                    student.setPassword(AesUtil.encrypt(pass));
                    LocalDate currentDate = LocalDate.now();
                    int year = currentDate.getYear();
                    student.setGrade(String.valueOf(year));
                    student.setEntryDate(currentDate);
                }

                saveBatch(insertPile);
            }

        }
    }

    @Override
    public void insertStudentList(StudentImportDto studentImportDto) {
        if (studentImportDto != null) {
            if (!StringUtils.hasLength(studentImportDto.getCollegeName())) {
                throw new CustomException("11", "请选择学院");
            }
            if (!StringUtils.hasLength(studentImportDto.getMajorName())) {
                throw new CustomException("11", "请选择专业信息");
            }
            Student student = studentMapper.selectOne(new LambdaQueryWrapper<Student>()
                    // .eq(Student::getDeleted, 0)
                    .eq(Student::getIdCardNo, studentImportDto.getIdCardNo())
            );
            if (student != null) {
                throw new CustomException("11", "该学生已经存在");
            }
            Major major = majorMapper.selectOne(new LambdaQueryWrapper<Major>()
                    //     .eq(Major::getDeleted, 0)
                    .eq(Major::getMajorName, studentImportDto.getMajorName())
            );
            if (major == null || !StringUtils.hasLength(major.getCollegeId())) {
                throw new CustomException("11", "专业或学院信息填写错误");
            }
            studentImportDto.setCollegeId(major.getCollegeId());
            studentImportDto.setMajorId(major.getSid());
            Student students = new Student();
            BeanUtils.copyProperties(students, studentImportDto);
            String pass = student.getIdCardNo().substring(student.getIdCardNo().length() - 6);
            student.setPassword(pass);
            if (students != null) {
                save(students);
            }
        }
    }


    /**
     * 解析excel
     *
     * @param file
     * @return
     */
    private List<Student> getExcelInfos(MultipartFile file) {
        List<StudentImportDto> result = new ArrayList<>();
        String fileName = file.getOriginalFilename();
        if (!fileName.contains(".xlsx")) {
            throw new CustomException("-17", "文件格式不正确");
        }
        Workbook workbook = getWorkbook(file);
        Sheet sheet = workbook.getSheet("Sheet1");
        for (int i = 0; i <= sheet.getLastRowNum(); i++) {
            if (sheet.getRow(i) == null) {
                continue;
            }
            for (int j = 0; j < 8; j++) {
                setCellType(j, sheet.getRow(i));
            }
        }
        //校验表头信息
        Row titleRow = sheet.getRow(1);
        //表头检验错误进行提示
        if (ExcelStudentEnum.isInclude(titleRow.getCell(0).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(1).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(2).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(3).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(4).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(5).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(6).getStringCellValue())
                || ExcelStudentEnum.isInclude(titleRow.getCell(7).getStringCellValue())) {
            throw new CustomException("11", "请使用正确的模板");
        }
        int exceptionLongNum = 0;//长度检验
        int exceptionNullNum = 0;//为空检验
        int exceptionIdNum = 0;//身份检验
        int timeNum = 0;//入学年份检验
        int studentSnNum = 0;//学生
        int majorNum = 0;//专业检验

        //将表格中的信息存入studentImportDto
        for (int i = 2; i <= sheet.getLastRowNum(); i++) {
            StudentImportDto studentImportDto = new StudentImportDto();
            Row rows = sheet.getRow(i);
            if (rows == null) {
                continue;
            }
            //获取姓名
            String studentName = rows.getCell(0) == null ? null : rows.getCell(0).getStringCellValue();
            if (!StringUtils.hasLength(studentName)) {
                exceptionNullNum = 1;
            }
            //获取身份证号
            String idCardNo = rows.getCell(1) == null ? null : rows.getCell(1).getStringCellValue();
            //非空校验
            if (!StringUtils.hasLength(idCardNo)) {
                exceptionNullNum = 1;
            }
            ///身份检验
            if (StringUtils.hasLength(idCardNo)) {
                boolean idNumber = isIDNumber(idCardNo);
                if (!idNumber) {
                    exceptionIdNum = 1;
                }
            }
            //性别
            String gender = rows.getCell(2) == null ? null : rows.getCell(2).getStringCellValue();
            //非空校验
            if (!StringUtils.hasLength(gender)) {
                exceptionNullNum = 1;
            }//长度检验
            if (StringUtils.hasLength(gender) && gender.length() > 2) {
                exceptionLongNum = 1;
            }
            //院系
            String collegeName = rows.getCell(3) == null ? null : rows.getCell(3).getStringCellValue(); //非空校验
            if (!StringUtils.hasLength(collegeName)) {
                exceptionNullNum = 1;
            }
            if (!StringUtils.hasLength(collegeName) && collegeName.length() > 25) {
                exceptionLongNum = 1;
            }
            //专业 MAJOR_NAME;
            String majorName = rows.getCell(4) == null ? null : rows.getCell(4).getStringCellValue();
            if (!StringUtils.hasLength(majorName)) {
                exceptionNullNum = 1;
            }
            if (!StringUtils.hasLength(majorName) && majorName.length() > 15) {
                exceptionLongNum = 1;
            }
            //民族 ;nation;
            String nation = rows.getCell(5) == null ? null : rows.getCell(5).getStringCellValue();
            if (!StringUtils.hasLength(nation)) {
                exceptionNullNum = 1;
            }
            if (!StringUtils.hasLength(nation) && nation.length() > 25) {
                exceptionLongNum = 1;
            }
            //入学年份
            String grade = rows.getCell(6) == null ? null : rows.getCell(6).getStringCellValue();
            if (!StringUtils.hasLength(grade)) {
                exceptionNullNum = 1;
            }
            if (!StringUtils.hasLength(grade) && grade.length() > 4) {
                timeNum = 1;
            }
            //入学省份
            String domicilePlaceProvince = rows.getCell(7) == null ? null : rows.getCell(7).getStringCellValue();
            if (!StringUtils.hasLength(domicilePlaceProvince)) {
                exceptionNullNum = 1;
            }
            if (!StringUtils.hasLength(grade) && grade.length() > 4) {
                exceptionLongNum = 1;
            }


            studentImportDto.setStudentName(studentName);//姓名
            studentImportDto.setIdCardNo(idCardNo);//身份证
            studentImportDto.setGrade(grade);//入学年份
            studentImportDto.setGender(gender);//性别
            studentImportDto.setNation(nation);//名族
            studentImportDto.setMajorName(majorName);//展专业名
            studentImportDto.setCollegeName(collegeName);//学院
            studentImportDto.setDomicilePlaceProvince(domicilePlaceProvince);
            result.add(studentImportDto);
        }
        //根据身份id 校验是否有重复的学生  过滤为空的sn在比较检验Collectors.groupingBy(Student::getStudentName,

        Map<String, Long> collect = result.stream().filter(t -> !StringUtils.hasLength(t.getStudentName()) && !StringUtils.hasLength(t.getIdCardNo())).collect(Collectors.groupingBy(StudentImportDto::getIdCardNo, Collectors.counting()));//Collectors.counting()
        List<String> idCard = collect.entrySet().stream().filter(entry -> entry.getValue() > 1).map(entry -> entry.getKey()).collect(toList());
        if (idCard.size() > 0) {
            studentSnNum = 1;
        }
        String collegeId = null;
        //判断是否存在当前专业 已经启用专业
        List<Major> majorList = majorService.queryMaj(collegeId, 1);
        //按照专业名名分组   进行判匹配//
        if (!CollectionUtils.isEmpty(majorList)) {
            Map<String, List<Major>> pileMap = majorList.stream().collect(groupingBy(Major::getMajorName));
            if (!CollectionUtils.isEmpty(result) && !CollectionUtils.isEmpty(majorList)) {
                for (StudentImportDto studentImportDto : result) {
                    if (studentImportDto != null && !StringUtils.hasLength(studentImportDto.getMajorName()) && CollectionUtils.isEmpty(pileMap.get(studentImportDto.getCollegeName()))) {
                        majorNum = 1;
                    }
                }
                for (StudentImportDto studentImportDto : result) {
                    for (Major major : majorList) {
                        if (major.getMajorName().equals(studentImportDto.getMajorName())) {
                            studentImportDto.setMajorId(major.getSid());
                            studentImportDto.setCollegeId(major.getCollegeId());
                        }
                    }
                }

            }
        }
        //校验错误信息
        if (exceptionLongNum + exceptionNullNum + exceptionIdNum + studentSnNum + majorNum + timeNum > 1) {
            throw new CustomException("-18", "上传失败，请仔细阅读规则按要求填写");
        } else if (exceptionNullNum == 1) {
            throw new CustomException("-18", "上传失败，必填项存在未填写");
        } else if (exceptionLongNum == 1) {
            throw new CustomException("-18", "上传失败，字符长度超出限制");
        } else if (majorNum == 1) {
            throw new CustomException("-18", "上传失败,当前专业填写错误或请先维护专业信息");
        } else if (studentSnNum == 1) {
            throw new CustomException("-18", "上传失败,学生信息重复");
        } else if (exceptionIdNum == 1) {
            throw new CustomException("-18", "上传失败,身份证号存在填写错误");
        } else if (timeNum == 1) {
            throw new CustomException("-18", "上传失败,年份填写错误");
        }
        List<Student> students = new ArrayList<>();
        if (!CollectionUtils.isEmpty(result)) {
            students = BeanConvertUtils.copyListProperties(result, Student::new);
        }
        return students;
    }

    /**
     * 设置单元格格式
     *
     * @param i
     * @param rows
     */
    private void setCellType(int i, Row rows) {
        if (rows.getCell(i) != null) {
            //rows.getCell(i).setCellType(Cell.CELL_TYPE_STRING);
            rows.getCell(i).setCellType(CellType.STRING);
        }
    }

    /**
     * .xls结尾还是.xlsx结尾所对应的Workbook不同
     *
     * @param file
     * @return
     */
    private Workbook getWorkbook(MultipartFile file) {
        InputStream is = null;
        Workbook wb = null;
        try {
            is = file.getInputStream();
            wb = new XSSFWorkbook(is);
        } catch (IOException e) {
            log.error("文件流异常:{}" + e);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                log.error("文件流异常:{}" + e);
            }
        }
        return wb;
    }
}
